﻿using System;
using System.Collections.Generic;

/*
 * -- Pattern Responsibilities and Restrictions --
 *  Definition: An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.
 *  Active Record is a good choice for domain logic that isn't too complex, such as creates, reads, updates, and deletes. Derivations and validations based on a single record work well in this structure
 *  
 * Data Container:- 
 * 1 database table should be mapped to one data container class. However is simple 1:* mapping (such as inheritence) can also be implemented.
 * OPTIONAL: Data container names should be identical
 * 
 * Data Container Fields:-
 * REQUIRED: 1 database table column should be mapped to one field of the corresponding data container class
 * OPTIONAL: Extra fields are allowed on any side.
 * OPTIONAL: Field names should be identical
 * OPTIONAL: Foreign key mapping to database fields
 * REQUIRED: Computation can be implemented on fields (i.e. derived fields) in the class ** primary difference from RowDataGateway **
 * OPTIONAL: Validation logic (i.e. email/phone format etc) on data fields
 * 
 * CRUD Method :-
 * REQUIRED: Data container and CRUD methods are placed in same class
 * RECOMMENDED: Insert/Update method type: instance
 * RECOMMENDED: Insert/Update method parameter - no parameter is needed
 * RECOMMENDED: Delete/Get method type: static methods if in same class. Instance methods if in seperate class (for testability).
 * RECOMMENDED: Delete/Get method parameter: By Id etc
 * 
 * Business Logic :-
 * REQUIRED: Simple computational logic (non-field level) can be included ** primary difference from RowDataGateway **
 * REQUIRED: No transactional/workflow logic can be included
 * 
 * Guideline :-
 * It often helps to wrap the tables as a Gateway first, and then start moving behavior so that the tables evolve to a Active Record.
*/

namespace ActiveRecordSample
{
    public class Company
    {
        public int CompanyId { get; set; }
        public string CompanyName { get; set; }
    }

    public class EmployeeActiveRecord
    {
        public int EmployeeId { get; set; }
        public string Name { get; set; }
        public string Email { get; set; } 
        public double MonthlySalary { get; set; }
        //You may consider Foreign Key Mapping (236), but you may also leave the foreign keys as they are. 
        public Company Company { get; set; }

        //Active Record can have business logic
        public double CalculateYearlyBonus() 
        {
            if (MonthlySalary > 10000)
                return MonthlySalary * 0.1; //10% bonus
            else
                return MonthlySalary * 0.05; //5% bonus
        }

        public EmployeeActiveRecord() { }

        public void Insert() { throw new NotImplementedException(); }
        public void Update() { throw new NotImplementedException(); }

        //by design principle/cohesion, delete/read methods should be instance method
        //we can move this static methods to another class, if we need instance method (for testability purpose etc)
        public static void Delete(int EmployeeId) { }
        public static EmployeeActiveRecord GetById(int EmployeeId) { throw new NotImplementedException(); }
        public static IList<EmployeeActiveRecord> GetByCompanyId(int companyId) { throw new NotImplementedException(); }
        public static IList<EmployeeActiveRecord> GetByCompany(Company company) { throw new NotImplementedException(); }
    }
}
